// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

/////////////////////////////////////////////////////////////////////////////
////
// This file was auto-generated by a tool at 2022-04-27 09:53:39
//
// It is recommended you DO NOT directly edit this file but instead edit
// the code-generator that generated this source file instead.
/////////////////////////////////////////////////////////////////////////////

#ifndef BITONIC_SORT_AVX512_INT32_T_H
#define BITONIC_SORT_AVX512_INT32_T_H


#ifdef __GNUC__
#ifdef __clang__
#pragma clang attribute push (__attribute__((target("avx512f"))), apply_to = any(function))
#else
#pragma GCC push_options
#pragma GCC target("avx512f")
#endif
#endif

#include <immintrin.h>
#include "bitonic_sort.h"

#define i2d _mm512_castsi512_pd
#define d2i _mm512_castpd_si512
#define i2s _mm512_castsi512_ps
#define s2i _mm512_castps_si512
#define s2d _mm512_castps_pd
#define d2s _mm521_castpd_ps

namespace vxsort {
namespace smallsort {
template<> struct bitonic<int32_t, AVX512> {
    static const int N = 16;
    static constexpr int32_t MAX = std::numeric_limits<int32_t>::Max();
public:

    static INLINE void sort_01v_ascending(__m512i& d01) {
        __m512i  min, s;

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xAAAA, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_ABCD);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xCCCC, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xAAAA, s, d01);

        s = _mm512_permutex_epi64(_mm512_shuffle_epi32(d01, _MM_PERM_ABCD), _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xF0F0, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xCCCC, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xAAAA, s, d01);

        s = _mm512_shuffle_i64x2(_mm512_shuffle_epi32(d01, _MM_PERM_ABCD), _mm512_shuffle_epi32(d01, _MM_PERM_ABCD), _MM_PERM_ABCD);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xFF00, s, d01);

        s = _mm512_permutex_epi64(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xF0F0, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xCCCC, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xAAAA, s, d01);
    }
    static INLINE void sort_01v_merge_ascending(__m512i& d01) {
        __m512i  min, s;

        s = _mm512_shuffle_i64x2(d01, d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xFF00, s, d01);

        s = _mm512_permutex_epi64(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xF0F0, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xCCCC, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0xAAAA, s, d01);
    }
    static INLINE void sort_01v_descending(__m512i& d01) {
        __m512i  min, s;

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x5555, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_ABCD);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x3333, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x5555, s, d01);

        s = _mm512_permutex_epi64(_mm512_shuffle_epi32(d01, _MM_PERM_ABCD), _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x0F0F, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x3333, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x5555, s, d01);

        s = _mm512_shuffle_i64x2(_mm512_shuffle_epi32(d01, _MM_PERM_ABCD), _mm512_shuffle_epi32(d01, _MM_PERM_ABCD), _MM_PERM_ABCD);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x00FF, s, d01);

        s = _mm512_permutex_epi64(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x0F0F, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x3333, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x5555, s, d01);
    }
    static INLINE void sort_01v_merge_descending(__m512i& d01) {
        __m512i  min, s;

        s = _mm512_shuffle_i64x2(d01, d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x00FF, s, d01);

        s = _mm512_permutex_epi64(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x0F0F, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_BADC);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x3333, s, d01);

        s = _mm512_shuffle_epi32(d01, _MM_PERM_CDAB);
        min = _mm512_min_epi32(s, d01);
        d01 = _mm512_mask_max_epi32(min, 0x5555, s, d01);
    }
    static INLINE void sort_02v_ascending(__m512i& d01, __m512i& d02) {
        __m512i  tmp;

        sort_01v_ascending(d01);
        sort_01v_descending(d02);

        tmp = d02;
        d02 = _mm512_max_epi32(d01, d02);
        d01 = _mm512_min_epi32(d01, tmp);

        sort_01v_merge_ascending(d01);
        sort_01v_merge_ascending(d02);
    }
    static INLINE void sort_02v_descending(__m512i& d01, __m512i& d02) {
        __m512i  tmp;

        sort_01v_descending(d01);
        sort_01v_ascending(d02);

        tmp = d02;
        d02 = _mm512_max_epi32(d01, d02);
        d01 = _mm512_min_epi32(d01, tmp);

        sort_01v_merge_descending(d01);
        sort_01v_merge_descending(d02);
    }
    static INLINE void sort_02v_merge_ascending(__m512i& d01, __m512i& d02) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d02, d01);
        d02 = _mm512_max_epi32(d02, tmp);

        sort_01v_merge_ascending(d01);
        sort_01v_merge_ascending(d02);
    }
    static INLINE void sort_02v_merge_descending(__m512i& d01, __m512i& d02) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d02, d01);
        d02 = _mm512_max_epi32(d02, tmp);

        sort_01v_merge_descending(d01);
        sort_01v_merge_descending(d02);
    }
    static INLINE void sort_03v_ascending(__m512i& d01, __m512i& d02, __m512i& d03) {
        __m512i  tmp;

        sort_02v_ascending(d01, d02);
        sort_01v_descending(d03);

        tmp = d03;
        d03 = _mm512_max_epi32(d02, d03);
        d02 = _mm512_min_epi32(d02, tmp);

        sort_02v_merge_ascending(d01, d02);
        sort_01v_merge_ascending(d03);
    }
    static INLINE void sort_03v_descending(__m512i& d01, __m512i& d02, __m512i& d03) {
        __m512i  tmp;

        sort_02v_descending(d01, d02);
        sort_01v_ascending(d03);

        tmp = d03;
        d03 = _mm512_max_epi32(d02, d03);
        d02 = _mm512_min_epi32(d02, tmp);

        sort_02v_merge_descending(d01, d02);
        sort_01v_merge_descending(d03);
    }
    static INLINE void sort_03v_merge_ascending(__m512i& d01, __m512i& d02, __m512i& d03) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d03, d01);
        d03 = _mm512_max_epi32(d03, tmp);

        sort_02v_merge_ascending(d01, d02);
        sort_01v_merge_ascending(d03);
    }
    static INLINE void sort_03v_merge_descending(__m512i& d01, __m512i& d02, __m512i& d03) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d03, d01);
        d03 = _mm512_max_epi32(d03, tmp);

        sort_02v_merge_descending(d01, d02);
        sort_01v_merge_descending(d03);
    }
    static NOINLINE void sort_04v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04) {
        __m512i  tmp;

        sort_02v_ascending(d01, d02);
        sort_02v_descending(d03, d04);

        tmp = d03;
        d03 = _mm512_max_epi32(d02, d03);
        d02 = _mm512_min_epi32(d02, tmp);

        tmp = d04;
        d04 = _mm512_max_epi32(d01, d04);
        d01 = _mm512_min_epi32(d01, tmp);

        sort_02v_merge_ascending(d01, d02);
        sort_02v_merge_ascending(d03, d04);
    }
    static NOINLINE void sort_04v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04) {
        __m512i  tmp;

        sort_02v_descending(d01, d02);
        sort_02v_ascending(d03, d04);

        tmp = d03;
        d03 = _mm512_max_epi32(d02, d03);
        d02 = _mm512_min_epi32(d02, tmp);

        tmp = d04;
        d04 = _mm512_max_epi32(d01, d04);
        d01 = _mm512_min_epi32(d01, tmp);

        sort_02v_merge_descending(d01, d02);
        sort_02v_merge_descending(d03, d04);
    }
    static NOINLINE void sort_04v_merge_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d03, d01);
        d03 = _mm512_max_epi32(d03, tmp);

        tmp = d02;
        d02 = _mm512_min_epi32(d04, d02);
        d04 = _mm512_max_epi32(d04, tmp);

        sort_02v_merge_ascending(d01, d02);
        sort_02v_merge_ascending(d03, d04);
    }
    static NOINLINE void sort_04v_merge_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d03, d01);
        d03 = _mm512_max_epi32(d03, tmp);

        tmp = d02;
        d02 = _mm512_min_epi32(d04, d02);
        d04 = _mm512_max_epi32(d04, tmp);

        sort_02v_merge_descending(d01, d02);
        sort_02v_merge_descending(d03, d04);
    }
    static INLINE void sort_05v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05) {
        __m512i  tmp;

        sort_04v_ascending(d01, d02, d03, d04);
        sort_01v_descending(d05);

        tmp = d05;
        d05 = _mm512_max_epi32(d04, d05);
        d04 = _mm512_min_epi32(d04, tmp);

        sort_04v_merge_ascending(d01, d02, d03, d04);
        sort_01v_merge_ascending(d05);
    }
    static INLINE void sort_05v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05) {
        __m512i  tmp;

        sort_04v_descending(d01, d02, d03, d04);
        sort_01v_ascending(d05);

        tmp = d05;
        d05 = _mm512_max_epi32(d04, d05);
        d04 = _mm512_min_epi32(d04, tmp);

        sort_04v_merge_descending(d01, d02, d03, d04);
        sort_01v_merge_descending(d05);
    }
    static INLINE void sort_05v_merge_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d05, d01);
        d05 = _mm512_max_epi32(d05, tmp);

        sort_04v_merge_ascending(d01, d02, d03, d04);
        sort_01v_merge_ascending(d05);
    }
    static INLINE void sort_05v_merge_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d05, d01);
        d05 = _mm512_max_epi32(d05, tmp);

        sort_04v_merge_descending(d01, d02, d03, d04);
        sort_01v_merge_descending(d05);
    }
    static INLINE void sort_06v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06) {
        __m512i  tmp;

        sort_04v_ascending(d01, d02, d03, d04);
        sort_02v_descending(d05, d06);

        tmp = d05;
        d05 = _mm512_max_epi32(d04, d05);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d06;
        d06 = _mm512_max_epi32(d03, d06);
        d03 = _mm512_min_epi32(d03, tmp);

        sort_04v_merge_ascending(d01, d02, d03, d04);
        sort_02v_merge_ascending(d05, d06);
    }
    static INLINE void sort_06v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06) {
        __m512i  tmp;

        sort_04v_descending(d01, d02, d03, d04);
        sort_02v_ascending(d05, d06);

        tmp = d05;
        d05 = _mm512_max_epi32(d04, d05);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d06;
        d06 = _mm512_max_epi32(d03, d06);
        d03 = _mm512_min_epi32(d03, tmp);

        sort_04v_merge_descending(d01, d02, d03, d04);
        sort_02v_merge_descending(d05, d06);
    }
    static INLINE void sort_06v_merge_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d05, d01);
        d05 = _mm512_max_epi32(d05, tmp);

        tmp = d02;
        d02 = _mm512_min_epi32(d06, d02);
        d06 = _mm512_max_epi32(d06, tmp);

        sort_04v_merge_ascending(d01, d02, d03, d04);
        sort_02v_merge_ascending(d05, d06);
    }
    static INLINE void sort_06v_merge_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d05, d01);
        d05 = _mm512_max_epi32(d05, tmp);

        tmp = d02;
        d02 = _mm512_min_epi32(d06, d02);
        d06 = _mm512_max_epi32(d06, tmp);

        sort_04v_merge_descending(d01, d02, d03, d04);
        sort_02v_merge_descending(d05, d06);
    }
    static INLINE void sort_07v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07) {
        __m512i  tmp;

        sort_04v_ascending(d01, d02, d03, d04);
        sort_03v_descending(d05, d06, d07);

        tmp = d05;
        d05 = _mm512_max_epi32(d04, d05);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d06;
        d06 = _mm512_max_epi32(d03, d06);
        d03 = _mm512_min_epi32(d03, tmp);

        tmp = d07;
        d07 = _mm512_max_epi32(d02, d07);
        d02 = _mm512_min_epi32(d02, tmp);

        sort_04v_merge_ascending(d01, d02, d03, d04);
        sort_03v_merge_ascending(d05, d06, d07);
    }
    static INLINE void sort_07v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07) {
        __m512i  tmp;

        sort_04v_descending(d01, d02, d03, d04);
        sort_03v_ascending(d05, d06, d07);

        tmp = d05;
        d05 = _mm512_max_epi32(d04, d05);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d06;
        d06 = _mm512_max_epi32(d03, d06);
        d03 = _mm512_min_epi32(d03, tmp);

        tmp = d07;
        d07 = _mm512_max_epi32(d02, d07);
        d02 = _mm512_min_epi32(d02, tmp);

        sort_04v_merge_descending(d01, d02, d03, d04);
        sort_03v_merge_descending(d05, d06, d07);
    }
    static INLINE void sort_07v_merge_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d05, d01);
        d05 = _mm512_max_epi32(d05, tmp);

        tmp = d02;
        d02 = _mm512_min_epi32(d06, d02);
        d06 = _mm512_max_epi32(d06, tmp);

        tmp = d03;
        d03 = _mm512_min_epi32(d07, d03);
        d07 = _mm512_max_epi32(d07, tmp);

        sort_04v_merge_ascending(d01, d02, d03, d04);
        sort_03v_merge_ascending(d05, d06, d07);
    }
    static INLINE void sort_07v_merge_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d05, d01);
        d05 = _mm512_max_epi32(d05, tmp);

        tmp = d02;
        d02 = _mm512_min_epi32(d06, d02);
        d06 = _mm512_max_epi32(d06, tmp);

        tmp = d03;
        d03 = _mm512_min_epi32(d07, d03);
        d07 = _mm512_max_epi32(d07, tmp);

        sort_04v_merge_descending(d01, d02, d03, d04);
        sort_03v_merge_descending(d05, d06, d07);
    }
    static NOINLINE void sort_08v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08) {
        __m512i  tmp;

        sort_04v_ascending(d01, d02, d03, d04);
        sort_04v_descending(d05, d06, d07, d08);

        tmp = d05;
        d05 = _mm512_max_epi32(d04, d05);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d06;
        d06 = _mm512_max_epi32(d03, d06);
        d03 = _mm512_min_epi32(d03, tmp);

        tmp = d07;
        d07 = _mm512_max_epi32(d02, d07);
        d02 = _mm512_min_epi32(d02, tmp);

        tmp = d08;
        d08 = _mm512_max_epi32(d01, d08);
        d01 = _mm512_min_epi32(d01, tmp);

        sort_04v_merge_ascending(d01, d02, d03, d04);
        sort_04v_merge_ascending(d05, d06, d07, d08);
    }
    static NOINLINE void sort_08v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08) {
        __m512i  tmp;

        sort_04v_descending(d01, d02, d03, d04);
        sort_04v_ascending(d05, d06, d07, d08);

        tmp = d05;
        d05 = _mm512_max_epi32(d04, d05);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d06;
        d06 = _mm512_max_epi32(d03, d06);
        d03 = _mm512_min_epi32(d03, tmp);

        tmp = d07;
        d07 = _mm512_max_epi32(d02, d07);
        d02 = _mm512_min_epi32(d02, tmp);

        tmp = d08;
        d08 = _mm512_max_epi32(d01, d08);
        d01 = _mm512_min_epi32(d01, tmp);

        sort_04v_merge_descending(d01, d02, d03, d04);
        sort_04v_merge_descending(d05, d06, d07, d08);
    }
    static NOINLINE void sort_08v_merge_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d05, d01);
        d05 = _mm512_max_epi32(d05, tmp);

        tmp = d02;
        d02 = _mm512_min_epi32(d06, d02);
        d06 = _mm512_max_epi32(d06, tmp);

        tmp = d03;
        d03 = _mm512_min_epi32(d07, d03);
        d07 = _mm512_max_epi32(d07, tmp);

        tmp = d04;
        d04 = _mm512_min_epi32(d08, d04);
        d08 = _mm512_max_epi32(d08, tmp);

        sort_04v_merge_ascending(d01, d02, d03, d04);
        sort_04v_merge_ascending(d05, d06, d07, d08);
    }
    static NOINLINE void sort_08v_merge_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08) {
        __m512i  tmp;

        tmp = d01;
        d01 = _mm512_min_epi32(d05, d01);
        d05 = _mm512_max_epi32(d05, tmp);

        tmp = d02;
        d02 = _mm512_min_epi32(d06, d02);
        d06 = _mm512_max_epi32(d06, tmp);

        tmp = d03;
        d03 = _mm512_min_epi32(d07, d03);
        d07 = _mm512_max_epi32(d07, tmp);

        tmp = d04;
        d04 = _mm512_min_epi32(d08, d04);
        d08 = _mm512_max_epi32(d08, tmp);

        sort_04v_merge_descending(d01, d02, d03, d04);
        sort_04v_merge_descending(d05, d06, d07, d08);
    }
    static INLINE void sort_09v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09) {
        __m512i  tmp;

        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_01v_descending(d09);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        sort_08v_merge_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_01v_merge_ascending(d09);
    }
    static INLINE void sort_09v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09) {
        __m512i  tmp;

        sort_08v_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_01v_ascending(d09);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        sort_08v_merge_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_01v_merge_descending(d09);
    }
    static INLINE void sort_10v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10) {
        __m512i  tmp;

        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_02v_descending(d09, d10);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        sort_08v_merge_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_02v_merge_ascending(d09, d10);
    }
    static INLINE void sort_10v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10) {
        __m512i  tmp;

        sort_08v_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_02v_ascending(d09, d10);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        sort_08v_merge_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_02v_merge_descending(d09, d10);
    }
    static INLINE void sort_11v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11) {
        __m512i  tmp;

        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_03v_descending(d09, d10, d11);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        sort_08v_merge_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_03v_merge_ascending(d09, d10, d11);
    }
    static INLINE void sort_11v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11) {
        __m512i  tmp;

        sort_08v_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_03v_ascending(d09, d10, d11);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        sort_08v_merge_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_03v_merge_descending(d09, d10, d11);
    }
    static NOINLINE void sort_12v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12) {
        __m512i  tmp;

        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_04v_descending(d09, d10, d11, d12);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        sort_08v_merge_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_04v_merge_ascending(d09, d10, d11, d12);
    }
    static NOINLINE void sort_12v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12) {
        __m512i  tmp;

        sort_08v_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_04v_ascending(d09, d10, d11, d12);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        sort_08v_merge_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_04v_merge_descending(d09, d10, d11, d12);
    }
    static INLINE void sort_13v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12, __m512i& d13) {
        __m512i  tmp;

        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_05v_descending(d09, d10, d11, d12, d13);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        tmp = d13;
        d13 = _mm512_max_epi32(d04, d13);
        d04 = _mm512_min_epi32(d04, tmp);

        sort_08v_merge_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_05v_merge_ascending(d09, d10, d11, d12, d13);
    }
    static INLINE void sort_13v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12, __m512i& d13) {
        __m512i  tmp;

        sort_08v_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_05v_ascending(d09, d10, d11, d12, d13);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        tmp = d13;
        d13 = _mm512_max_epi32(d04, d13);
        d04 = _mm512_min_epi32(d04, tmp);

        sort_08v_merge_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_05v_merge_descending(d09, d10, d11, d12, d13);
    }
    static INLINE void sort_14v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12, __m512i& d13, __m512i& d14) {
        __m512i  tmp;

        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_06v_descending(d09, d10, d11, d12, d13, d14);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        tmp = d13;
        d13 = _mm512_max_epi32(d04, d13);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d14;
        d14 = _mm512_max_epi32(d03, d14);
        d03 = _mm512_min_epi32(d03, tmp);

        sort_08v_merge_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_06v_merge_ascending(d09, d10, d11, d12, d13, d14);
    }
    static INLINE void sort_14v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12, __m512i& d13, __m512i& d14) {
        __m512i  tmp;

        sort_08v_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_06v_ascending(d09, d10, d11, d12, d13, d14);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        tmp = d13;
        d13 = _mm512_max_epi32(d04, d13);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d14;
        d14 = _mm512_max_epi32(d03, d14);
        d03 = _mm512_min_epi32(d03, tmp);

        sort_08v_merge_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_06v_merge_descending(d09, d10, d11, d12, d13, d14);
    }
    static INLINE void sort_15v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12, __m512i& d13, __m512i& d14, __m512i& d15) {
        __m512i  tmp;

        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_07v_descending(d09, d10, d11, d12, d13, d14, d15);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        tmp = d13;
        d13 = _mm512_max_epi32(d04, d13);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d14;
        d14 = _mm512_max_epi32(d03, d14);
        d03 = _mm512_min_epi32(d03, tmp);

        tmp = d15;
        d15 = _mm512_max_epi32(d02, d15);
        d02 = _mm512_min_epi32(d02, tmp);

        sort_08v_merge_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_07v_merge_ascending(d09, d10, d11, d12, d13, d14, d15);
    }
    static INLINE void sort_15v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12, __m512i& d13, __m512i& d14, __m512i& d15) {
        __m512i  tmp;

        sort_08v_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_07v_ascending(d09, d10, d11, d12, d13, d14, d15);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        tmp = d13;
        d13 = _mm512_max_epi32(d04, d13);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d14;
        d14 = _mm512_max_epi32(d03, d14);
        d03 = _mm512_min_epi32(d03, tmp);

        tmp = d15;
        d15 = _mm512_max_epi32(d02, d15);
        d02 = _mm512_min_epi32(d02, tmp);

        sort_08v_merge_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_07v_merge_descending(d09, d10, d11, d12, d13, d14, d15);
    }
    static NOINLINE void sort_16v_ascending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12, __m512i& d13, __m512i& d14, __m512i& d15, __m512i& d16) {
        __m512i  tmp;

        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_08v_descending(d09, d10, d11, d12, d13, d14, d15, d16);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        tmp = d13;
        d13 = _mm512_max_epi32(d04, d13);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d14;
        d14 = _mm512_max_epi32(d03, d14);
        d03 = _mm512_min_epi32(d03, tmp);

        tmp = d15;
        d15 = _mm512_max_epi32(d02, d15);
        d02 = _mm512_min_epi32(d02, tmp);

        tmp = d16;
        d16 = _mm512_max_epi32(d01, d16);
        d01 = _mm512_min_epi32(d01, tmp);

        sort_08v_merge_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_08v_merge_ascending(d09, d10, d11, d12, d13, d14, d15, d16);
    }
    static NOINLINE void sort_16v_descending(__m512i& d01, __m512i& d02, __m512i& d03, __m512i& d04, __m512i& d05, __m512i& d06, __m512i& d07, __m512i& d08, __m512i& d09, __m512i& d10, __m512i& d11, __m512i& d12, __m512i& d13, __m512i& d14, __m512i& d15, __m512i& d16) {
        __m512i  tmp;

        sort_08v_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_08v_ascending(d09, d10, d11, d12, d13, d14, d15, d16);

        tmp = d09;
        d09 = _mm512_max_epi32(d08, d09);
        d08 = _mm512_min_epi32(d08, tmp);

        tmp = d10;
        d10 = _mm512_max_epi32(d07, d10);
        d07 = _mm512_min_epi32(d07, tmp);

        tmp = d11;
        d11 = _mm512_max_epi32(d06, d11);
        d06 = _mm512_min_epi32(d06, tmp);

        tmp = d12;
        d12 = _mm512_max_epi32(d05, d12);
        d05 = _mm512_min_epi32(d05, tmp);

        tmp = d13;
        d13 = _mm512_max_epi32(d04, d13);
        d04 = _mm512_min_epi32(d04, tmp);

        tmp = d14;
        d14 = _mm512_max_epi32(d03, d14);
        d03 = _mm512_min_epi32(d03, tmp);

        tmp = d15;
        d15 = _mm512_max_epi32(d02, d15);
        d02 = _mm512_min_epi32(d02, tmp);

        tmp = d16;
        d16 = _mm512_max_epi32(d01, d16);
        d01 = _mm512_min_epi32(d01, tmp);

        sort_08v_merge_descending(d01, d02, d03, d04, d05, d06, d07, d08);
        sort_08v_merge_descending(d09, d10, d11, d12, d13, d14, d15, d16);
    }

    static NOINLINE void sort_01v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 0));
        sort_01v_ascending(d01);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 0, mask, d01);
    }

    static NOINLINE void sort_02v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 1));
        sort_02v_ascending(d01, d02);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 1, mask, d02);
    }

    static NOINLINE void sort_03v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 2));
        sort_03v_ascending(d01, d02, d03);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 2, mask, d03);
    }

    static NOINLINE void sort_04v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 3));
        sort_04v_ascending(d01, d02, d03, d04);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 3, mask, d04);
    }

    static NOINLINE void sort_05v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 4));
        sort_05v_ascending(d01, d02, d03, d04, d05);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 4, mask, d05);
    }

    static NOINLINE void sort_06v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 5));
        sort_06v_ascending(d01, d02, d03, d04, d05, d06);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 5, mask, d06);
    }

    static NOINLINE void sort_07v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 6));
        sort_07v_ascending(d01, d02, d03, d04, d05, d06, d07);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 6, mask, d07);
    }

    static NOINLINE void sort_08v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 7));
        sort_08v_ascending(d01, d02, d03, d04, d05, d06, d07, d08);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 7, mask, d08);
    }

    static NOINLINE void sort_09v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_loadu_si512((__m512i const *) ptr + 7);;
        __m512i d09 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 8));
        sort_09v_ascending(d01, d02, d03, d04, d05, d06, d07, d08, d09);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_storeu_si512((__m512i *) ptr + 7, d08);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 8, mask, d09);
    }

    static NOINLINE void sort_10v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_loadu_si512((__m512i const *) ptr + 7);;
        __m512i d09 = _mm512_loadu_si512((__m512i const *) ptr + 8);;
        __m512i d10 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 9));
        sort_10v_ascending(d01, d02, d03, d04, d05, d06, d07, d08, d09, d10);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_storeu_si512((__m512i *) ptr + 7, d08);
        _mm512_storeu_si512((__m512i *) ptr + 8, d09);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 9, mask, d10);
    }

    static NOINLINE void sort_11v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_loadu_si512((__m512i const *) ptr + 7);;
        __m512i d09 = _mm512_loadu_si512((__m512i const *) ptr + 8);;
        __m512i d10 = _mm512_loadu_si512((__m512i const *) ptr + 9);;
        __m512i d11 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 10));
        sort_11v_ascending(d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_storeu_si512((__m512i *) ptr + 7, d08);
        _mm512_storeu_si512((__m512i *) ptr + 8, d09);
        _mm512_storeu_si512((__m512i *) ptr + 9, d10);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 10, mask, d11);
    }

    static NOINLINE void sort_12v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_loadu_si512((__m512i const *) ptr + 7);;
        __m512i d09 = _mm512_loadu_si512((__m512i const *) ptr + 8);;
        __m512i d10 = _mm512_loadu_si512((__m512i const *) ptr + 9);;
        __m512i d11 = _mm512_loadu_si512((__m512i const *) ptr + 10);;
        __m512i d12 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 11));
        sort_12v_ascending(d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11, d12);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_storeu_si512((__m512i *) ptr + 7, d08);
        _mm512_storeu_si512((__m512i *) ptr + 8, d09);
        _mm512_storeu_si512((__m512i *) ptr + 9, d10);
        _mm512_storeu_si512((__m512i *) ptr + 10, d11);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 11, mask, d12);
    }

    static NOINLINE void sort_13v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_loadu_si512((__m512i const *) ptr + 7);;
        __m512i d09 = _mm512_loadu_si512((__m512i const *) ptr + 8);;
        __m512i d10 = _mm512_loadu_si512((__m512i const *) ptr + 9);;
        __m512i d11 = _mm512_loadu_si512((__m512i const *) ptr + 10);;
        __m512i d12 = _mm512_loadu_si512((__m512i const *) ptr + 11);;
        __m512i d13 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 12));
        sort_13v_ascending(d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11, d12, d13);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_storeu_si512((__m512i *) ptr + 7, d08);
        _mm512_storeu_si512((__m512i *) ptr + 8, d09);
        _mm512_storeu_si512((__m512i *) ptr + 9, d10);
        _mm512_storeu_si512((__m512i *) ptr + 10, d11);
        _mm512_storeu_si512((__m512i *) ptr + 11, d12);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 12, mask, d13);
    }

    static NOINLINE void sort_14v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_loadu_si512((__m512i const *) ptr + 7);;
        __m512i d09 = _mm512_loadu_si512((__m512i const *) ptr + 8);;
        __m512i d10 = _mm512_loadu_si512((__m512i const *) ptr + 9);;
        __m512i d11 = _mm512_loadu_si512((__m512i const *) ptr + 10);;
        __m512i d12 = _mm512_loadu_si512((__m512i const *) ptr + 11);;
        __m512i d13 = _mm512_loadu_si512((__m512i const *) ptr + 12);;
        __m512i d14 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 13));
        sort_14v_ascending(d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11, d12, d13, d14);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_storeu_si512((__m512i *) ptr + 7, d08);
        _mm512_storeu_si512((__m512i *) ptr + 8, d09);
        _mm512_storeu_si512((__m512i *) ptr + 9, d10);
        _mm512_storeu_si512((__m512i *) ptr + 10, d11);
        _mm512_storeu_si512((__m512i *) ptr + 11, d12);
        _mm512_storeu_si512((__m512i *) ptr + 12, d13);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 13, mask, d14);
    }

    static NOINLINE void sort_15v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_loadu_si512((__m512i const *) ptr + 7);;
        __m512i d09 = _mm512_loadu_si512((__m512i const *) ptr + 8);;
        __m512i d10 = _mm512_loadu_si512((__m512i const *) ptr + 9);;
        __m512i d11 = _mm512_loadu_si512((__m512i const *) ptr + 10);;
        __m512i d12 = _mm512_loadu_si512((__m512i const *) ptr + 11);;
        __m512i d13 = _mm512_loadu_si512((__m512i const *) ptr + 12);;
        __m512i d14 = _mm512_loadu_si512((__m512i const *) ptr + 13);;
        __m512i d15 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 14));
        sort_15v_ascending(d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11, d12, d13, d14, d15);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_storeu_si512((__m512i *) ptr + 7, d08);
        _mm512_storeu_si512((__m512i *) ptr + 8, d09);
        _mm512_storeu_si512((__m512i *) ptr + 9, d10);
        _mm512_storeu_si512((__m512i *) ptr + 10, d11);
        _mm512_storeu_si512((__m512i *) ptr + 11, d12);
        _mm512_storeu_si512((__m512i *) ptr + 12, d13);
        _mm512_storeu_si512((__m512i *) ptr + 13, d14);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 14, mask, d15);
    }

    static NOINLINE void sort_16v_alt(int32_t *ptr, int remainder) {
        const auto mask = (uint16_t)(0xFFFF >> ((N - remainder) & (N-1)));

        __m512i d01 = _mm512_loadu_si512((__m512i const *) ptr + 0);;
        __m512i d02 = _mm512_loadu_si512((__m512i const *) ptr + 1);;
        __m512i d03 = _mm512_loadu_si512((__m512i const *) ptr + 2);;
        __m512i d04 = _mm512_loadu_si512((__m512i const *) ptr + 3);;
        __m512i d05 = _mm512_loadu_si512((__m512i const *) ptr + 4);;
        __m512i d06 = _mm512_loadu_si512((__m512i const *) ptr + 5);;
        __m512i d07 = _mm512_loadu_si512((__m512i const *) ptr + 6);;
        __m512i d08 = _mm512_loadu_si512((__m512i const *) ptr + 7);;
        __m512i d09 = _mm512_loadu_si512((__m512i const *) ptr + 8);;
        __m512i d10 = _mm512_loadu_si512((__m512i const *) ptr + 9);;
        __m512i d11 = _mm512_loadu_si512((__m512i const *) ptr + 10);;
        __m512i d12 = _mm512_loadu_si512((__m512i const *) ptr + 11);;
        __m512i d13 = _mm512_loadu_si512((__m512i const *) ptr + 12);;
        __m512i d14 = _mm512_loadu_si512((__m512i const *) ptr + 13);;
        __m512i d15 = _mm512_loadu_si512((__m512i const *) ptr + 14);;
        __m512i d16 = _mm512_mask_loadu_epi32(_mm512_set1_epi32(MAX),
                                              mask,
                                              (int32_t const *) ((__m512i const *) ptr + 15));
        sort_16v_ascending(d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11, d12, d13, d14, d15, d16);
        _mm512_storeu_si512((__m512i *) ptr + 0, d01);
        _mm512_storeu_si512((__m512i *) ptr + 1, d02);
        _mm512_storeu_si512((__m512i *) ptr + 2, d03);
        _mm512_storeu_si512((__m512i *) ptr + 3, d04);
        _mm512_storeu_si512((__m512i *) ptr + 4, d05);
        _mm512_storeu_si512((__m512i *) ptr + 5, d06);
        _mm512_storeu_si512((__m512i *) ptr + 6, d07);
        _mm512_storeu_si512((__m512i *) ptr + 7, d08);
        _mm512_storeu_si512((__m512i *) ptr + 8, d09);
        _mm512_storeu_si512((__m512i *) ptr + 9, d10);
        _mm512_storeu_si512((__m512i *) ptr + 10, d11);
        _mm512_storeu_si512((__m512i *) ptr + 11, d12);
        _mm512_storeu_si512((__m512i *) ptr + 12, d13);
        _mm512_storeu_si512((__m512i *) ptr + 13, d14);
        _mm512_storeu_si512((__m512i *) ptr + 14, d15);
        _mm512_mask_storeu_epi32((__m512i *) ptr + 15, mask, d16);
    }
    static void sort(int32_t *ptr, size_t length);

};
}
}

#undef i2d
#undef d2i
#undef i2s
#undef s2i
#undef s2d
#undef d2s

#ifdef __GNUC__
#ifdef __clang__
#pragma clang attribute pop
#else
#pragma GCC pop_options
#endif
#endif
#endif

